home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
system
/
icpuid3a.zip
/
CPUID3.ASM
next >
Wrap
Assembly Source File
|
1994-01-04
|
18KB
|
543 lines
; Filename: cpuid32.msm
;
; This program has been developed by Intel Corporation. You have
; Intel's permission to incorporate this source code into your
; product royalty free.
;
; Intel specifically disclaims all warranties, express or implied,
; and all liability, including consequential and other indirect
; damages, for the use of this code, including liability for
; infringement of any proprietary rights. Intel does not assume
; any responsibility for any errors which may appear in this code
; nor any responsibility to update it.
;
; This program contains three parts:
; Part 1: Identifies CPU type in the variable cpu_type:
; 0=8086 processor
; 2=Intel 286 processor
; 3=Intel386(TM) processor
; 4=Intel486(TM) processor
; 5=Pentium(TM) processor
;
; Part 2: Identifies FPU type in the variable fpu_type:
; 0=FPU not present
; 1=FPU present
; 2=287 present (only if cpu_type=3)
; 3=387 present (only if cpu_type=3)
;
; Part 3: Prints out the appropriate message. This part can
; be removed if this program is not used in a DOS-based
; system. Portions affected are at the end of the
; data segment and the print procedure in the code
; segment.
;
; REVISION HISTORY:
; Date: 4/93
; 1. Replaced the .486 with .186 to avoid generation of 0FH type long
; conditional branches (such as the branch to end_get_cpuid at
; the end of the 8086/8088 test, near code address 003D). These
; are not executable on the 8086/8088 and 80286, so the code falls
; into some strange place and hangs the system. The .186 also allows
; multi-bit shifts to unpack CPUID info. Using .186 requires
; that all 32-bit operand prefix (66H) be inserted by hand.
; This is done with a macro (OPND32).
; 2. Avoid all usage of 32-bit operands until it is clear that the
; CPU is at least an 80386. The use of the Exx registers caused
; the generation of the 66H prefix, which are not executed
; correctly on the 8086/8088 and 80286.
; 3. Eliminated all the register save/restore and added comment
; that all registers are used by the functions.
; 4. Do the stack alignment just before messing with the AC bit in
; EFLAGS, otherwise the stack may not be properly aligned. Also
; restore the AC bit immediately, so it does not stay set.
; 5. Changed the FPU detection to set one flag fpu_type (instead of
; the previous two flags: fpu_present and infinity). An fpu_type
; of zero indicates no floating point unit is present, an fpu_type
; of 2 indicates an 80287 is present, an fpu_type of 3 indicates
; an 80387 is present.
;
; If this code is assembled with MASM with no options specified, it
; runs correctly on an 8086/8088, 80286, 80386, 80486, and
; Pentium(tm) processor.
;
TITLE CPUID
DOSSEG
.model small
.stack 100h
.186
OPND32 MACRO op_code, op_erand
db 66h ; Force 32-bit operand size
IFNB <op_code>
db op_code
IFNB <op_erand>
dd op_erand; 32-bit immediate value
ENDIF
ENDIF
ENDM
CPUID MACRO
db 0fh ; Hardcoded opcode for CPUID instruction
db 0a2h
ENDM
TRUE equ 1
FAMILY_MASK equ 0f00h
FAMILY_SHIFT equ 8
MODEL_MASK equ 0f0h
MODEL_SHIFT equ 4
STEPPING_MASK equ 0fh
FPU_FLAG equ 1h
MCE_FLAG equ 80h
CMPXCHG8B_FLAG equ 100h
.data
fp_status dw ?
vendor_id db 12 dup (?)
cpu_type db ?
modell db ?
stepping db ?
id_flag db 0
fpu_type db 0
intel_proc db 0
feature_flags dw 2 dup (0)
;
; remove the remaining data declarations if not using the DOS-based
; print procedure
;
id_msg db "This system has a$"
fp_8087 db " and an 8087 math coprocessor$"
fp_80287 db " and an 80287 math coprocessor$"
fp_80387 db " and an 80387 math coprocessor$"
c8086 db "n 8086/8088 processor$"
c286 db "n 80286 processor$"
c386 db "n 80386 processor$"
c486 db "n 80486 DX processor or 80487 SX math coprocessor$"
c486nfp db "n 80486 SX processor$"
Intel486_msg db 13,10,"This system contains a Genuine Intel486(TM) processor",13,10,"$"
Pentium_msg db 13,10,"This system contains a Genuine Intel Pentium(TM) processor",13,10,"$"
modelmsg db "Model: $"
steppingmsg db "Stepping: $"
familymsg db 13,10,"Processor Family: $"
period db ".",13,10,"$"
dataCR db ?,13,10,"$"
intel_id db "GenuineIntel"
fpu_msg db 13,10,"This processor contains a FPU",13,10,"$"
mce_msg db "This processor supports the Machine Check Exception",13,10,"$"
cmp_msg db "This processor supports the CMPXCHG8B instruction",13,10,"$"
not_intel db "t least an 80486 processor.",13,10
db "It does not contain a Genuine Intel part and as a result,",13,10
db "the CPUID detection information cannot be determined at this time.",13,10,"$"
;
; The purpose of this code is to identify the processor and
; coprocessor that is currently in the system. The program first
; determines the processor id. When that is accomplished,
; the program then determines whether a coprocessor
; exists in the system. If a coprocessor or integrated
; coprocessor exists, the program identifies
; the coprocessor id. The program then prints out
; the CPU and floating point presence and type.
;
.code
start: mov ax, @data
mov ds, ax ; set segment register
mov es, ax ; set segment register
pushf ; save for restoration at end
call get_cpuid
call get_fpuid
call print
popf
mov ax, 4c00h ; terminate program
int 21h
get_cpuid proc
;
; This procedure determines the type of CPU in a system
; and sets the cpu_type variable with the appropriate
; value.
; All registers are used by this procedure, none are preserved.
; Intel 8086 CPU check
; Bits 12-15 of the FLAGS register are always set on the
; 8086 processor.
;
check_8086:
pushf ; push original FLAGS
pop ax ; get original FLAGS
mov cx, ax ; save original FLAGS
and ax, 0fffh ; clear bits 12-15 in FLAGS
push ax ; save new FLAGS value on stack
popf ; replace current FLAGS value
pushf ; get new FLAGS
pop ax ; store new FLAGS in AX
and ax, 0f000h ; if bits 12-15 are set, then CPU
cmp ax, 0f000h ; is an 8086/8088
mov cpu_type, 0 ; turn on 8086/8088 flag
jne check_80286 ; jump if CPU is not 8086/8088
jmp end_get_cpuid
; Intel 286 CPU check
; Bits 12-15 of the FLAGS register are always clear on the
; Intel 286 processor in real-address mode.
;
check_80286:
or cx, 0f000h ; try to set bits 12-15
push cx ; save new FLAGS value on stack
popf ; replace current FLAGS value
pushf ; get new FLAGS
pop ax ; store new FLAGS in AX
and ax, 0f000h ; if bits 12-15 clear, CPU=80286
mov cpu_type, 2 ; turn on 80286 flag
jnz check_80386 ; if no bits set, CPU is 80286
jmp end_get_cpuid
; Intel386 CPU check
; The AC bit, bit #18, is a new bit introduced in the EFLAGS
; regist